package com.along.utility.common.utils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/*
 *@Author: liujinyi
 *@CreateTime: 2025-08-22
 *@Description: 对称加密和非对称加密
 *@Version: 1.0
 */
public class encryptionUtils {

    /**
     * @param plaintext
     * @param key
     * @Author: liujinyi
     * @Description: 对称加密
     * @Date: 2025/8/22 10:51
     * @Return: java.lang.String
     **/
    // AES加密方法
    public static String encrypt(String plaintext, SecretKey key) throws Exception {
        // 获取AES加密器（使用GCM模式，提供认证功能）
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

        // 生成随机IV（初始化向量）
        byte[] iv = new byte[12];
        java.security.SecureRandom random = new java.security.SecureRandom();
        random.nextBytes(iv);

        // 初始化加密器
        GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv);
        cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);

        // 执行加密
        byte[] cipherText = cipher.doFinal(plaintext.getBytes("UTF-8"));

        // 组合IV和密文
        byte[] encryptedData = new byte[iv.length + cipherText.length];
        System.arraycopy(iv, 0, encryptedData, 0, iv.length);
        System.arraycopy(cipherText, 0, encryptedData, iv.length, cipherText.length);

        // 返回Base64编码的字符串
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    // AES解密方法
    public static String decrypt(String encryptedData, SecretKey key) throws Exception {
        // 解码Base64字符串
        byte[] decodedData = Base64.getDecoder().decode(encryptedData);

        // 分离IV和密文
        byte[] iv = new byte[12];
        byte[] cipherText = new byte[decodedData.length - 12];
        System.arraycopy(decodedData, 0, iv, 0, 12);
        System.arraycopy(decodedData, 12, cipherText, 0, cipherText.length);

        // 获取AES解密器
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

        // 初始化解密器
        GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv);
        cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);

        // 执行解密
        byte[] plaintext = cipher.doFinal(cipherText);

        return new String(plaintext, "UTF-8");
    }


    /**
     * @Author: liujinyi
     * @Description: 非对称加密
     * @Date: 2025/8/22 10:51
     * @Return: KeyPair
     **/
    // 生成RSA密钥对
    public static KeyPair generateKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048); // 使用2048位密钥
        return keyPairGenerator.generateKeyPair();
    }

    // 使用公钥加密
    public static String encrypt(String plaintext, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        byte[] cipherText = cipher.doFinal(plaintext.getBytes("UTF-8"));
        return Base64.getEncoder().encodeToString(cipherText);
    }

    // 使用私钥解密
    public static String decrypt(String ciphertext, PrivateKey privateKey) throws Exception {
        byte[] bytes = Base64.getDecoder().decode(ciphertext);

        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        return new String(cipher.doFinal(bytes), "UTF-8");
    }

    // 将公钥转换为字符串
    public static String publicKeyToString(PublicKey publicKey) {
        return Base64.getEncoder().encodeToString(publicKey.getEncoded());
    }

    // 将字符串转换为公钥
    public static PublicKey stringToPublicKey(String publicKeyString) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(publicKeyString);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(spec);
    }

    // 将私钥转换为字符串
    public static String privateKeyToString(PrivateKey privateKey) {
        return Base64.getEncoder().encodeToString(privateKey.getEncoded());
    }

    // 将字符串转换为私钥
    public static PrivateKey stringToPrivateKey(String privateKeyString) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(privateKeyString);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(spec);
    }

    public static void main(String[] args) {
        //对称加密
        try {
            // 生成AES密钥
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(256); // 使用256位密钥
            SecretKey secretKey = keyGenerator.generateKey();

            // 原始消息
            String originalMessage = "这是一条需要加密的敏感信息!";
            System.out.println("原始消息: " + originalMessage);

            // 加密
            String encryptedMessage = encrypt(originalMessage, secretKey);
            System.out.println("加密后的消息: " + encryptedMessage);

            // 解密
            String decryptedMessage = decrypt(encryptedMessage, secretKey);
            System.out.println("解密后的消息: " + decryptedMessage);

            // 验证
            if (originalMessage.equals(decryptedMessage)) {
                System.out.println("加解密成功! 消息一致。");
            } else {
                System.out.println("加解密失败! 消息不一致。");
            }

        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
        // 非对称加密
        try {
            // 生成密钥对
            KeyPair keyPair = generateKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();

            // 原始消息
            String originalMessage = "这是一条需要非对称加密的敏感信息!";
            System.out.println("原始消息: " + originalMessage);

            // 使用公钥加密
            String encryptedMessage = encrypt(originalMessage, publicKey);
            System.out.println("加密后的消息: " + encryptedMessage);

            // 使用私钥解密
            String decryptedMessage = decrypt(encryptedMessage, privateKey);
            System.out.println("解密后的消息: " + decryptedMessage);

            // 验证
            if (originalMessage.equals(decryptedMessage)) {
                System.out.println("加解密成功! 消息一致。");
            } else {
                System.out.println("加解密失败! 消息不一致。");
            }

            // 演示密钥的保存和加载
            System.out.println("\n--- 密钥保存与加载演示 ---");
            String publicKeyStr = publicKeyToString(publicKey);
            String privateKeyStr = privateKeyToString(privateKey);

            System.out.println("公钥字符串: " + publicKeyStr.substring(0, 50) + "...");
            System.out.println("私钥字符串: " + privateKeyStr.substring(0, 50) + "...");

            // 从字符串加载密钥
            PublicKey loadedPublicKey = stringToPublicKey(publicKeyStr);
            PrivateKey loadedPrivateKey = stringToPrivateKey(privateKeyStr);

            // 使用加载的密钥进行加密解密
            String testMessage = "测试密钥加载功能!";
            String testEncrypted = encrypt(testMessage, loadedPublicKey);
            String testDecrypted = decrypt(testEncrypted, loadedPrivateKey);

            System.out.println("密钥加载测试: " + (testMessage.equals(testDecrypted) ? "成功" : "失败"));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
